#include <iostream>

// namespace允许像类，对象，函数聚集在一个名字下
using namespace std;

class Box
{

private:
  int *width;

public:
  double x, y;
  double getx(void);
  Box(int num);        // 定义构造函数
  Box(const Box &box); //定义拷贝构造函数
  ~Box()
  {
    cout << "我是析构函数: 我用来释放资源" << endl;
    width = 0;
    delete width;
  };
  friend void print(Box box); // 定义友元函数
  friend class BigBox;        // 定义友元类
};

Box::Box(int num)
{
  cout << "我是构造函数： 我用来初始化" << endl;
  cout << "为 width 分配内存" << endl;
  width = new int; // 分配内存
  *width = num;    // 赋值
}

Box::Box(const Box &box)
{
  cout << "我是拷贝构造函数： 我用来在类之间赋值的时候进行调用: box1 = box" << endl;
  width = new int;     // 为 width 分配内存
  *width = *box.width; // 取到 box 中的 width 值，同时赋值给 *width;
}

// 范围边界访问 :: 只能定义在外部
double Box::getx(void)
{
  // 函数中可以访问 Box 中的成员变量
  cout << x << endl;
  cout << width << endl; // 88
  x = 10;
  return x;
}

// 外部实现友元函数
// NOTE: 友元函数
void print(Box box)
{ // 友元函数中可以直接访问类中的任意成员变量
  cout << "call 友元函数" << endl;
  cout << "Width of box : " << *box.width << endl;
}

// NOTE: 友元类的实现
class BigBox
{
public:
  int h;
  void printW(Box box) // 函数不能和外部函数名相同， 否则会被编译器认为是一个友元函数，但是没有使用 friend 关键字来修饰, 会导致编译器报错
  {
    cout << "call 友元类" << endl;
    this->h = 100;
    cout << "Width of box : " << *box.width << endl;
    // NOTE: this 是指向类本身的指针类型，那么指针类型在访问成员变量的时候， 需要使用 -> 单箭头
    cout << "this->h of box : " << this->h << endl;
  }
};

int main(int argc, char const *argv[])
{

  Box b(10);
  Box b1 = b;
  // b.x = 20;
  b1 = b; // 这里会需要实现拷贝构造函数来实现，因为这里会调用拷贝构造函数
  double m = b.getx();
  cout << m << endl;
  print(b); // NOTE: 友元函数的调用
  BigBox big;

  big.printW(b);
  // cout << b.width << endl; // 不可访问， 编译报错
  return 0;
}
